import pygame
import abc
import typing
import math


CollidableObjs = typing.Union[list[pygame.sprite.Sprite], pygame.sprite.Group]


class CollisionShape(metaclass=abc.ABCMeta):
    """
    定义Area检测区域形状的基类。
    """
    
    def __init__(self, pos: pygame.Vector2 = pygame.Vector2()) -> None:
        self.pos: pygame.Vector2 = pos
        self.draw_color: pygame.Color = pygame.Color(0, 255, 0, 100)

    @abc.abstractmethod
    def draw(self, surface: pygame.Surface, *args, **kwargs) -> None:
        pass

    @abc.abstractmethod
    def collide(self, obj: pygame.sprite.Sprite) -> bool:
        pass


class RectCollisionShape(CollisionShape):
    """
    矩形检测区域
    """
    
    def __init__(self, rect: pygame.Rect) -> None:
        super().__init__(pygame.Vector2(rect.topleft))
        self.rect = rect

    def draw(self, surface: pygame.Surface, *args, **kwargs) -> None:
        draw_surface =pygame.Surface(self.rect.size, pygame.SRCALPHA)
        pygame.draw.rect(draw_surface, self.draw_color, (0, 0, self.rect.width, self.rect.height))
        surface.blit(draw_surface, self.rect)

    def collide(self, obj: pygame.sprite.Sprite) -> bool:
        return self.rect.colliderect(obj.collision_rect)


class CircleCollisionShape(CollisionShape):
    """
    圆形检测区域
    """
    
    def __init__(self, pos: pygame.Vector2, radius: int) -> None:
        super().__init__(pos)
        self.radius = radius

    def draw(self, surface: pygame.Surface, *args, **kwargs) -> None:
        draw_surface =pygame.Surface((self.radius * 2, self.radius * 2), pygame.SRCALPHA)
        pygame.draw.circle(draw_surface, self.draw_color, (self.radius, self.radius), self.radius)
        surface.blit(draw_surface, self.pos - (self.radius, self.radius))
        # pygame.draw.circle(surface, self.draw_color, self.pos, self.radius)

    def collide(self, obj: pygame.sprite.Sprite) -> bool:
        if self.radius == 0:
            return False
        if self.pos == obj.rect.center and self.radius > 0:
            return True

        # 判断sprite在shape的那个方位，并设置距离计算点
        direction = (pygame.Vector2(obj.collision_rect.center) - self.pos).normalize()
        if direction.x == -1:
            check_point = (obj.collision_rect.right, obj.collision_rect.centery)
        elif direction.x == 1:
            check_point = (obj.collision_rect.left, obj.collision_rect.centery)
        elif direction.y == -1:
            check_point = (obj.collision_rect.centerx, obj.collision_rect.bottom)
        elif direction.y == 1:
            check_point = (obj.collision_rect.centerx, obj.collision_rect.top)
        elif direction.x < 0 and direction.y < 0:
            check_point = obj.collision_rect.bottomright
        elif direction.x > 0 and direction.y < 0:
            check_point = obj.collision_rect.bottomleft
        elif direction.x > 0 and direction.y > 0:
            check_point =  obj.collision_rect.topleft
        elif direction.x < 0 and direction.y > 0:
            check_point =  obj.collision_rect.topright

        if math.sqrt((check_point[0] - self.pos.x) ** 2 + (check_point[1] - self.pos.y) ** 2) <= self.radius:
            return True
        # if pygame.Vector2(check_point).distance_to(self.pos) <= self.radius:
        #     return True
        return False
        

class PolygonCollisionShape(CollisionShape):
    """
    多边形检测区域
    """
    
    def __init__(self, polygon: list[pygame.Vector2]) -> None:
        super().__init__()

        self.polygon = polygon

    def draw(self, surface: pygame.Surface, *args, **kwargs) -> None:
        pass

    def collide(self, obj: pygame.sprite.Sprite) -> bool:
        pass
